package com.lakeworks.framework.security.handle;

import com.lakeworks.common.core.domain.model.LoginUser;
import com.lakeworks.framework.web.service.TokenService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;

import static com.alibaba.fastjson2.JSON.toJSONString;
import static com.lakeworks.common.constant.HttpStatus.FORBIDDEN;
import static com.lakeworks.common.constant.HttpStatus.UNAUTHORIZED;
import static com.lakeworks.common.core.domain.AjaxResult.error;
import static com.lakeworks.common.utils.ServletUtils.renderString;
import static java.util.Objects.nonNull;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * 认证失败处理类 返回未授权
 *
 * @author lakeworks
 */
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {

    private static final long serialVersionUID = -8970718410437077606L;

    private static final Logger log = getLogger(AuthenticationEntryPointImpl.class);

    private static final String CHANNEL_PATTERN = "/channel/**";

    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Autowired
    private TokenService tokenService;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
        String requestUri = request.getRequestURI();
        String forwardUri = (String) request.getAttribute("javax.servlet.forward.request_uri");

        log.error("请求方式：[{}]，请求访问：[{}]，认证失败，无法访问系统资源", request.getMethod(), nonNull(forwardUri) ? forwardUri : requestUri, e);
        if (isNotBlank(forwardUri) && antPathMatcher.match(contextPath.concat(CHANNEL_PATTERN), forwardUri) || (isNotBlank(requestUri) && antPathMatcher.match(contextPath.concat(CHANNEL_PATTERN), requestUri))) {
            response.setStatus(UNAUTHORIZED);
        } else {
            LoginUser loginUser = tokenService.getLoginUser(request);
            renderString(
                    response, toJSONString(
                            loginUser == null ? error(UNAUTHORIZED, "认证失败，无法访问系统资") :
                                    loginUser.getPermissions().isEmpty() ?
                                            error(FORBIDDEN, "访问受限，没有权限") :
                                                error(UNAUTHORIZED, "认证失败，无法访问系统资")
                    ));
        }
    }
}
